import logging
from datetime import datetime

from mcp.server.fastmcp import FastMCP
import threading
import anyio
from common.db_util import MySqlDb
from invoice.models import Invoice, InvoiceItem

#声明MCP服务实例
mcp =  FastMCP("mcp-invoice-server",host="0.0.0.0",port=5000)

@mcp.tool()
def add_tool(x:int,y:int):
    """
    有两个数字相加的加法工具
    :param x: 第一个数字
    :param y: 第二个数字
    :return: 两个数字的和
    """
    logging.info(f"调用了加法工具add_tool: x={x}, y={y}")
    return x+y

@mcp.tool()
def sub_tool(x:int,y:int):
    """
    有两个数字相减的减法工具
    :param x: 第一个数字
    :param y: 第二个数字
    :return: 两个数字的差
    """
    logging.info(f"调用了减法工具sub_tool: x={x}, y={y}")
    return x-y

@mcp.tool()
def save_invoice(invoice:dict):
    """
    保存发票工具
    :param invoice: 发票数据字典
    : 字典invoice描述
     {
    "id": "发票主表 ID",
    "invoice_type": "发票类型",
    "invoice_code": "发票代码",
    "issue_date": "开票日期",
    "buyer_name": "购买方名称",
    "buyer_tax_id": "购买方税号",
    "buyer_address_phone": "购买方地址电话",
    "buyer_bank_account": "购买方开户行及账号",
    "seller_name": "销售方名称",
    "seller_tax_id": "销售方税号",
    "seller_address_phone": "销售方地址电话",
    "seller_bank_account": "销售方开户行及账号",
    "check_code": "校验码",
    "machine_code": "机器编号",
    "total_amount": "价税分离合计金额",
    "total_tax": "合计税额",
    "total_price_tax": "价税合计",
    "drawer": "开票人",
    "created_at": "创建时间",
    "updated_at": "更新时间",
    "items": [
                {
                    "id": "明细ID",
                    "item_name": "商品 / 服务名称",
                    "specification": "规格型号",
                    "unit": "单位",
                    "quantity": "数量",
                    "unit_price": "单价",
                    "amount": "明细金额（不含税）",
                    "tax_rate": "税率",
                    "tax_amount": "明细税额",
                    "created_at": "创建时间",
                    "updated_at": "更新时间"
                }
            ]
     }
    :return: 保存结果
    """
    logging.info(f"调用了保存发票工具save_invoice: invoice={invoice}")
    # 字典invoice转换成对象Invoice
    #invoice_obj = Invoice(**invoice)
    invoice_obj = Invoice()
    # 从字典中赋值
    invoice_obj.invoice_type = invoice["invoice_type"]
    invoice_obj.invoice_code = invoice["invoice_code"]
    invoice_obj.issue_date = invoice["issue_date"]
    invoice_obj.buyer_name = invoice["buyer_name"]
    invoice_obj.buyer_tax_id = invoice["buyer_tax_id"]
    invoice_obj.buyer_address_phone = invoice["buyer_address_phone"]
    invoice_obj.buyer_bank_account = invoice["buyer_bank_account"]
    invoice_obj.seller_name = invoice["seller_name"]
    invoice_obj.seller_tax_id = invoice["seller_tax_id"]
    invoice_obj.seller_address_phone = invoice["seller_address_phone"]
    invoice_obj.seller_bank_account = invoice["seller_bank_account"]
    invoice_obj.check_code = invoice["check_code"]
    invoice_obj.machine_code = invoice["machine_code"]
    invoice_obj.total_amount = invoice["total_amount"]
    invoice_obj.total_tax = invoice["total_tax"]
    invoice_obj.total_price_tax = invoice["total_price_tax"]
    invoice_obj.drawer = invoice["drawer"]
    # 直接取系统时间
    invoice_obj.created_at = datetime.now()
    invoice_obj.updated_at = datetime.now()
    # 使用同一个session来确保外键关系正确建立
    session = MySqlDb.get_mysql_session()
    try:
        # 首先存储发票的主表
        session.add(invoice_obj)
        session.flush()  # 刷新以获取生成的ID，但不提交事务

        invoice_items = invoice["items"]
        # 保存发票明细
        for item in invoice_items:
            # 转换成发票明细对象
            item_obj = InvoiceItem(**item)
            # 关联发票主表ID（现在可以获取到了）
            item_obj.invoice_id = invoice_obj.id
            # 添加到session
            session.add(item_obj)

        # 提交整个事务
        session.commit()
        logging.info(f"发票保存成功，发票ID: {invoice_obj.id}")

        return {"code": 200, "status": "success", "message": "发票保存成功", "invoice_id": invoice_obj.id}

    except Exception as e:
        # 回滚事务
        session.rollback()
        logging.error(f"保存发票失败: {str(e)}")
        return {"code": 500, "status": "error", "message": f"保存发票失败: {str(e)}"}

    finally:
        # 关闭session
        session.close()




@mcp.tool()
def save_invoice_with_useId(invoice:dict, dify_user_id:str):
    """
    保存发票工具，关联dify用户ID
    :param invoice: 发票数据字典
    :param dify_user_id: dify用户ID
    # 字典invoice描述
     {
    "id": "发票主表 ID",
    "invoice_type": "发票类型",
    "invoice_code": "发票代码",
    "issue_date": "开票日期",
    "buyer_name": "购买方名称",
    "buyer_tax_id": "购买方税号",
    "buyer_address_phone": "购买方地址电话",
    "buyer_bank_account": "购买方开户行及账号",
    "seller_name": "销售方名称",
    "seller_tax_id": "销售方税号",
    "seller_address_phone": "销售方地址电话",
    "seller_bank_account": "销售方开户行及账号",
    "check_code": "校验码",
    "machine_code": "机器编号",
    "total_amount": "价税分离合计金额",
    "total_tax": "合计税额",
    "total_price_tax": "价税合计",
    "drawer": "开票人",
    "created_at": "创建时间",
    "updated_at": "更新时间",
    "items": [
                {
                    "id": "明细ID",
                    "item_name": "商品 / 服务名称",
                    "specification": "规格型号",
                    "unit": "单位",
                    "quantity": "数量",
                    "unit_price": "单价",
                    "amount": "明细金额（不含税）",
                    "tax_rate": "税率",
                    "tax_amount": "明细税额",
                    "created_at": "创建时间",
                    "updated_at": "更新时间"
                }
            ]
     }
    :return: 保存结果
    """
    logging.info(f"调用了保存发票工具save_invoice: invoice={invoice}")
    # 字典invoice转换成对象Invoice
    #invoice_obj = Invoice(**invoice)
    invoice_obj = Invoice()
    # 从字典中赋值
    invoice_obj.invoice_type = invoice["invoice_type"]
    invoice_obj.invoice_code = invoice["invoice_code"]
    invoice_obj.issue_date = invoice["issue_date"]
    invoice_obj.buyer_name = invoice["buyer_name"]
    invoice_obj.buyer_tax_id = invoice["buyer_tax_id"]
    invoice_obj.buyer_address_phone = invoice["buyer_address_phone"]
    invoice_obj.buyer_bank_account = invoice["buyer_bank_account"]
    invoice_obj.seller_name = invoice["seller_name"]
    invoice_obj.seller_tax_id = invoice["seller_tax_id"]
    invoice_obj.seller_address_phone = invoice["seller_address_phone"]
    invoice_obj.seller_bank_account = invoice["seller_bank_account"]
    invoice_obj.check_code = invoice["check_code"]
    invoice_obj.machine_code = invoice["machine_code"]
    invoice_obj.total_amount = invoice["total_amount"]
    invoice_obj.total_tax = invoice["total_tax"]
    invoice_obj.total_price_tax = invoice["total_price_tax"]
    invoice_obj.drawer = invoice["drawer"]
    invoice_obj.dify_user_id = dify_user_id
    # 直接取系统时间
    invoice_obj.created_at = datetime.now()
    invoice_obj.updated_at = datetime.now()
    # 使用同一个session来确保外键关系正确建立
    session = MySqlDb.get_mysql_session()
    try:
        # 首先存储发票的主表
        session.add(invoice_obj)
        session.flush()  # 刷新以获取生成的ID，但不提交事务

        invoice_items = invoice["items"]
        # 保存发票明细
        for item in invoice_items:
            # 转换成发票明细对象
            item_obj = InvoiceItem(**item)
            # 关联发票主表ID（现在可以获取到了）
            item_obj.invoice_id = invoice_obj.id
            # 添加到session
            session.add(item_obj)

        # 提交整个事务
        session.commit()
        logging.info(f"发票保存成功，发票ID: {invoice_obj.id}")

        return {"code": 200, "status": "success", "message": "发票保存成功", "invoice_id": invoice_obj.id}

    except Exception as e:
        # 回滚事务
        session.rollback()
        logging.error(f"保存发票失败: {str(e)}")
        return {"code": 500, "status": "error", "message": f"保存发票失败: {str(e)}"}

    finally:
        # 关闭session
        session.close()
@mcp.tool()
def query_invoice(invoice_id: str):
    """
    查询发票工具
    :param invoice_id: 发票主表ID
    :return: 发票数据字典
    """
    logging.info(f"调用了查询发票工具query_invoice: invoice_id={invoice_id}")
    # 从数据库查询发票详情,使用query方法
    sql = """
    SELECT * FROM invoice WHERE id = :invoice_id
    """
    params = {"invoice_id": invoice_id}
    invoice_result = MySqlDb.query(sql, params)
    if not invoice_result:
        return {"code": 404, "status": "error", "message": "发票不存在"}

    # 获取发票主表数据
    invoice_obj = invoice_result[0]

    # 从数据库查询发票明细,使用query方法
    sql = """
    SELECT * FROM invoice_item WHERE invoice_id = :invoice_id
    """
    params = {"invoice_id": invoice_id}
    item_objs = MySqlDb.query(sql, params)

    # 组装返回结果数据
    result = {
        "id": invoice_obj.get("id"),
        "invoice_type": invoice_obj.get("invoice_type"),
        "invoice_code": invoice_obj.get("invoice_code"),
        "issue_date": invoice_obj.get("issue_date"),
        "buyer_name": invoice_obj.get("buyer_name"),
        "buyer_tax_id": invoice_obj.get("buyer_tax_id"),
        "buyer_address_phone": invoice_obj.get("buyer_address_phone"),
        "buyer_bank_account": invoice_obj.get("buyer_bank_account"),
        "seller_name": invoice_obj.get("seller_name"),
        "seller_tax_id": invoice_obj.get("seller_tax_id"),
        "seller_address_phone": invoice_obj.get("seller_address_phone"),
        "seller_bank_account": invoice_obj.get("seller_bank_account"),
        "check_code": invoice_obj.get("check_code"),
        "machine_code": invoice_obj.get("machine_code"),
        "total_amount": invoice_obj.get("total_amount"),
        "total_tax": invoice_obj.get("total_tax"),
        "total_price_tax": invoice_obj.get("total_price_tax"),
        "drawer": invoice_obj.get("drawer"),
        "created_at": invoice_obj.get("created_at"),
        "updated_at": invoice_obj.get("updated_at"),
        "items": item_objs
    }
    logging.info(f"===查询发票成功，发票详情: {result}")

    return {"code": 200, "status": "success", "data": result}


def start_mcp_background():
    """在新线程中启动 MCP 服务"""

    def run_mcp():
        # 确保新线程有自己的 Django 上下文
        import django
        django.setup()

        print("========== 在后台线程启动 MCP 服务 =================")
        try:
            # 直接使用 anyio 运行异步方法
            anyio.run(mcp.run_sse_async)
        except Exception as e:
            print(f"MCP 服务启动失败: {e}")

    # 创建并启动守护线程
    thread = threading.Thread(target=run_mcp, daemon=True)
    thread.start()
    print("MCP 服务已在后台线程启动")


# 在 Django 启动时调用此函数
if __name__ == "__main__":
    start_mcp_background()
# if __name__ == "__main__":
#     mcp.run(transport="sse")